{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# Pull Portfolio Factor Risk Data with GS Quant\n",
    "\n",
    "## Step 1: Authenticate and Initialize Your Session\n",
    "\n",
    "First you will import the necessary modules and add your client id and client secret."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from IPython.display import display\n",
    "import datetime as dt\n",
    "\n",
    "from gs_quant.markets.portfolio_manager import PortfolioManager\n",
    "from gs_quant.markets.report import FactorRiskUnit, FactorRiskTableMode\n",
    "from gs_quant.markets.securities import SecurityMaster, AssetIdentifier\n",
    "from gs_quant.session import GsSession, Environment\n",
    "\n",
    "client = None\n",
    "secret = None\n",
    "\n",
    "\n",
    "## External users must fill in their client ID and secret below and comment out the line below\n",
    "# client = 'ENTER CLIENT ID'\n",
    "# secret = 'ENTER CLIENT SECRET'\n",
    "\n",
    "GsSession.use(\n",
    "    Environment.PROD,\n",
    "    client_id=client,\n",
    "    client_secret=secret,\n",
    ")\n",
    "\n",
    "print('GS Session initialized.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## Step 2: Get Portfolio Factor Risk Report"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "risk_report = PortfolioManager('ENTER PORTFOLIO ID').get_factor_risk_report(risk_model_id='RISK MODEL ID')\n",
    "\n",
    "print(f'Factor risk report found with ID: {risk_report.id}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Want to query data for an active risk report? Leverage the `SecurityMaster` class to retrieve the benchmark identifier and\n",
    "pass it into the `get_factor_risk_report` function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "benchmark = SecurityMaster.get_asset(id_value='SPX', id_type=AssetIdentifier.BLOOMBERG_ID)\n",
    "\n",
    "risk_report = PortfolioManager('ENTER PORTFOLIO ID').get_factor_risk_report(\n",
    "    risk_model_id='AXIOMA_AXUSWW4', benchmark_id=benchmark.get_marquee_id()\n",
    ")\n",
    "\n",
    "print(f'Factor risk report found with ID: {risk_report.id}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## Step 3: Current Portfolio Risk\n",
    "\n",
    "Once your risk report is scheduled as of the latest business day, you can view updated risk data broken down by factor category:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "category_table = risk_report.get_view(\n",
    "    start_date=risk_report.latest_end_date, end_date=risk_report.latest_end_date, unit=FactorRiskUnit.Notional\n",
    ").get('factorCategoriesTable')\n",
    "\n",
    "category_df = pd.DataFrame(category_table).filter(\n",
    "    items=[\n",
    "        'name',\n",
    "        'proportionOfRisk',\n",
    "        'marginalContributionToRiskPercent',\n",
    "        'relativeMarginalContributionToRisk',\n",
    "        'exposure',\n",
    "        'avgProportionOfRisk',\n",
    "    ]\n",
    ")\n",
    "category_df.rename(\n",
    "    columns={\n",
    "        'proportionOfRisk': 'Prop. of Risk',\n",
    "        'marginalContributionToRiskPercent': 'MCTR Percent',\n",
    "        'relativeMarginalContributionToRisk': 'MCTR (USD)',\n",
    "        'exposure': 'Exposure (USD)',\n",
    "        'avgProportionOfRisk': 'Avg Prop. of Risk',\n",
    "    },\n",
    "    inplace=True,\n",
    ")\n",
    "\n",
    "display(category_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "It is also possible to get a similar table for all the factors in a factor category. In this case, let's pull risk data for all the Style factors:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "factor_table = risk_report.get_view(\n",
    "    factor_category='Style',\n",
    "    start_date=risk_report.latest_end_date,\n",
    "    end_date=risk_report.latest_end_date,\n",
    "    unit=FactorRiskUnit.Notional,\n",
    ").get('factorsTable')\n",
    "\n",
    "factor_df = pd.DataFrame(factor_table).filter(\n",
    "    items=[\n",
    "        'name',\n",
    "        'proportionOfRisk',\n",
    "        'marginalContributionToRiskPercent',\n",
    "        'relativeMarginalContributionToRisk',\n",
    "        'exposure',\n",
    "        'avgProportionOfRisk',\n",
    "    ]\n",
    ")\n",
    "factor_df.rename(\n",
    "    columns={\n",
    "        'proportionOfRisk': 'Prop. of Risk',\n",
    "        'marginalContributionToRiskPercent': 'MCTR %',\n",
    "        'relativeMarginalContributionToRisk': 'MCTR (USD)',\n",
    "        'exposure': 'Exposure (USD)',\n",
    "        'avgProportionOfRisk': 'Avg Prop. of Risk',\n",
    "    },\n",
    "    inplace=True,\n",
    ")\n",
    "\n",
    "display(factor_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "For an asset-level risk breakdown for a set of factors, leverage the get_table() function on the FactorRiskReport class. In this case, let's see the Z-Scores for the factors Beta, Dividend Yield, and Downside Risk:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "zscore_table = risk_report.get_table(\n",
    "    mode=FactorRiskTableMode.ZScore,\n",
    "    factors=[\"Beta\", \"Dividend Yield\", \"Downside Risk\"],\n",
    "    date=dt.date(2025, 1, 29),  # Define the date for which you are looking to query the report on\n",
    ")\n",
    "\n",
    "display(pd.DataFrame(zscore_table))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## Step 4: Historical Portfolio Risk\n",
    "\n",
    "First let's pull the daily annualized risk across the duration of your portfolio:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "risk_data = risk_report.get_results(\n",
    "    start_date=risk_report.earliest_start_date, end_date=risk_report.latest_end_date, unit=FactorRiskUnit.Notional\n",
    ")\n",
    "\n",
    "historical_risk = risk_data[risk_data['factor'] == 'Total'][['date', 'annualRisk']].set_index('date')\n",
    "\n",
    "historical_risk = pd.DataFrame(historical_risk)\n",
    "\n",
    "historical_risk.plot(title='Annualized Risk % (ex-ante)')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "For each day, you can see what percent of your risk is contributed to factor risk and what percent is idiosyncratic:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "historical_risk = risk_data[risk_data['factor'].isin(['Specific', 'Factor'])][\n",
    "    ['date', 'factor', 'annualRisk']\n",
    "].set_index('date')\n",
    "\n",
    "# Formatting the data for plotting\n",
    "historical_risk = historical_risk.pivot(columns='factor', values='annualRisk')\n",
    "historical_risk.reset_index(inplace=True)\n",
    "historical_risk.rename(columns={'Factor': 'Factor Risk', 'Specific': 'Specific Risk'}, inplace=True)\n",
    "\n",
    "historical_risk.plot(x='date', y=['Factor Risk', 'Specific Risk'], title='Factor and Specific Risk')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "It's even possible to break down that factor risk further by category.\n",
    "\n",
    "Let's start by just seeing the universe of **Factor Categories** in our risk report."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "risk_data = risk_report.get_results(\n",
    "    start_date=risk_report.earliest_start_date, end_date=risk_report.latest_end_date, unit=FactorRiskUnit.Notional\n",
    ")\n",
    "\n",
    "print(risk_data[\"factorCategory\"].unique())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Factor categories allow to plot factor risk that falls under the specificied universe."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "factor_categories = ['Style', 'Market']\n",
    "\n",
    "prop_of_risk = risk_report.get_factor_proportion_of_risk(\n",
    "    factor_categories=factor_categories,\n",
    "    start_date=risk_report.earliest_start_date,\n",
    "    end_date=risk_report.latest_end_date,\n",
    ").set_index('Date')\n",
    "\n",
    "prop_of_risk.plot(title=f'Proportion of Risk By Factor Categories: {factor_categories}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "And by factors within a category. In this case, let's try the Style factors:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "factor_categories = ['Style']\n",
    "factor_names = ['Dividend Yield', 'Earnings Yield', 'Growth']\n",
    "\n",
    "prop_of_risk = risk_report.get_factor_proportion_of_risk(\n",
    "    factor_categories=factor_categories,\n",
    "    factor_names=factor_names,\n",
    "    start_date=risk_report.earliest_start_date,\n",
    "    end_date=risk_report.latest_end_date,\n",
    ").set_index('Date')\n",
    "\n",
    "prop_of_risk.plot(title='Proportion of Risk of Style Factors')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "*Other questions? Reach out to the [Portfolio Analytics team](mailto:gs-marquee-analytics-support@gs.com)!*"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
